/*
 * UNIVERSIDADE FEDERAL DE CAMPINA GRANDE
 *   CENTRO DE ENGENHARIA E INFORMATICA
 *     CURSO DE CIENCIA DA COMPUTACAO
 *     
 * Disciplina: Inteligencia Artificial
 * Professora: Joseana Macedo Fechine
 * Projeto: IA_DAMAS
 * Equipe de Desenvolvimento:
 * 		Alan de Farias Cruz
 * 		Anderson Pablo L. Silva
 * 		Rafael Dantas Araujo
 * 
*/

package util;

import java.util.*;

/**
 * Classe para listas genericas
 */
public class List implements Cloneable {
  private ListNode head;
  private ListNode tail;
  private int count;

  public List() {
    count = 0;
  }
  
  /**
   * Adiciona um elemento no inicio da lista
   */
  public void push_front (Object elem) {
    ListNode node = new ListNode (elem, null, head);
    
    if (head != null)
      head.prev = node;
    else
      tail = node;

    head = node;
    count++;
  }

  /**
   * Adiciona um elemento na rabo da lista
   */
  public void push_back (Object elem) {
    ListNode node = new ListNode (elem, tail, null);

    if (tail != null)
      tail.next = node;
    else
      head = node;

    tail = node;
    count++;
  }

  /**
   * Remove o elemento do inicio da lista e retorna
   */
  public Object pop_front() {
    if (head == null)
      return null;

    ListNode node = head;
    head = head.next;

    if (head != null)
      head.prev = null;
    else
      tail = null;

    count--;
    return node.value;
  }

  /**
   * Remove o elemento do fim da lista e retorna
   */
  public Object pop_back() {
    if (tail == null)
      return null;

    ListNode node = tail;
    tail = tail.prev;

    if (tail != null)
      tail.next = null;
    else
      head = null;

    count--;
    return node.value;
  }


  /**
   * Diz se a lista e' vazia
   */
  public boolean isEmpty() {
    return head == null;
  }


  /**
   * Retorna o numero de elementos na lista
   */
  public int length() {
    return count;
  }

  /**
   * Acrescenta outra lista a this
   * @param other list that is to be appended.
   */
  public void append (List other) {
    ListNode node = other.head;
    
    while (node != null) {
      push_back (node.value);
      node = node.next;
    }
  }
  

  /**
   * Limpa a lista
   */
  public void clear() {
    head = tail = null;
  }


  /**
   * Retorna o elemento do inicio da lista sem remover
   */
  public Object peek_head() {
    if (head != null)
      return head.value;
    else
      return null;
  }

  /**
   * Retorna o elemento do fim da lista sem remover
   */
  public Object peek_tail() {
    if (tail != null)
      return tail.value;
    else
      return null;
  }
  
  /**
   * Verifica se o elemento existe na lista
   */
  public boolean has (Object elem) {
    ListNode node = head;

    while (node != null && !node.value.equals (elem))
      node = node.next;

    return node != null;
  }

  /**
   * Clona a lista
   */
  public Object clone() {
    List temp = new List();
    ListNode node = head;

    while (node != null) {
      //temp.push_back (node.value.clone());
      temp.push_back (node.value);
      node = node.next;
    }

    return temp;
  }

  /**
   * Retorna uma representacao em string
   */
  public String toString() {
    String temp = "[";
    ListNode node = head;

    while (node != null) {
      temp += node.value.toString();
      node = node.next;
      if (node != null)
        temp += ", ";
    }
    temp += "]";

    return temp;
  }

  /**
   * Retorna uma enumeracao dos elementos da lista
   */
  @SuppressWarnings("unchecked")
  public Enumeration elements() {
    return new Enum (head);
  }
  
  
}

  
